"""
辅助函数模块
提供各种通用的辅助函数
"""

import os
import cv2
import json
import csv
import pandas as pd
import numpy as np
from pathlib import Path
from typing import List, Tuple, Dict, Any, Optional
from datetime import datetime


def ensure_dir(path: str) -> Path:
    """
    确保目录存在，如不存在则创建
    
    参数:
        path (str): 目录路径
        
    返回:
        Path: 目录路径对象
    """
    dir_path = Path(path)
    dir_path.mkdir(parents=True, exist_ok=True)
    return dir_path


def get_timestamp(format: str = "%Y%m%d_%H%M%S") -> str:
    """
    获取当前时间戳字符串
    
    参数:
        format (str): 时间格式
        
    返回:
        str: 时间戳字符串
    """
    return datetime.now().strftime(format)


def resize_image(image: np.ndarray, 
                 max_width: int = 1280, 
                 max_height: int = 720) -> np.ndarray:
    """
    调整图像大小，保持宽高比
    
    参数:
        image (np.ndarray): 输入图像
        max_width (int): 最大宽度
        max_height (int): 最大高度
        
    返回:
        np.ndarray: 调整后的图像
    """
    height, width = image.shape[:2]
    
    # 计算缩放比例
    scale = min(max_width / width, max_height / height)
    
    if scale < 1:
        new_width = int(width * scale)
        new_height = int(height * scale)
        return cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA)
    
    return image


def draw_bbox(image: np.ndarray,
              bbox: List[int],
              label: str,
              color: Tuple[int, int, int] = (0, 255, 0),
              thickness: int = 2) -> np.ndarray:
    """
    在图像上绘制边界框和标签
    
    参数:
        image (np.ndarray): 输入图像
        bbox (List[int]): 边界框坐标 [x1, y1, x2, y2]
        label (str): 标签文本
        color (Tuple[int, int, int]): 框的颜色 (B, G, R)
        thickness (int): 线条粗细
        
    返回:
        np.ndarray: 绘制后的图像
    """
    x1, y1, x2, y2 = bbox
    
    # 绘制边界框
    cv2.rectangle(image, (x1, y1), (x2, y2), color, thickness)
    
    # 计算标签背景大小
    font = cv2.FONT_HERSHEY_SIMPLEX
    font_scale = 0.6
    (label_width, label_height), _ = cv2.getTextSize(label, font, font_scale, 1)
    
    # 绘制标签背景
    cv2.rectangle(image, 
                  (x1, y1 - label_height - 4), 
                  (x1 + label_width + 4, y1), 
                  color, -1)
    
    # 绘制标签文本
    cv2.putText(image, label, 
                (x1 + 2, y1 - 2), 
                font, font_scale, 
                (255, 255, 255), 1, cv2.LINE_AA)
    
    return image


def save_results_csv(results: List[Dict[str, Any]], 
                     output_path: str) -> None:
    """
    将识别结果保存为CSV文件
    
    参数:
        results (List[Dict]): 识别结果列表
        output_path (str): 输出文件路径
    """
    if not results:
        return
        
    # 确保输出目录存在
    ensure_dir(Path(output_path).parent)
    
    # 获取所有键
    keys = results[0].keys()
    
    # 写入CSV
    with open(output_path, 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.DictWriter(f, fieldnames=keys)
        writer.writeheader()
        writer.writerows(results)


def save_results_json(results: List[Dict[str, Any]], 
                      output_path: str) -> None:
    """
    将识别结果保存为JSON文件
    
    参数:
        results (List[Dict]): 识别结果列表
        output_path (str): 输出文件路径
    """
    # 确保输出目录存在
    ensure_dir(Path(output_path).parent)
    
    # 写入JSON
    with open(output_path, 'w', encoding='utf-8') as f:
        json.dump(results, f, ensure_ascii=False, indent=2)


def save_results_excel(results: List[Dict[str, Any]], 
                       output_path: str,
                       sheet_name: str = "车牌识别结果") -> None:
    """
    将识别结果保存为Excel文件
    
    参数:
        results (List[Dict]): 识别结果列表
        output_path (str): 输出文件路径
        sheet_name (str): 工作表名称
    """
    if not results:
        return
        
    # 确保输出目录存在
    ensure_dir(Path(output_path).parent)
    
    # 转换为DataFrame
    df = pd.DataFrame(results)
    
    # 写入Excel
    with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
        df.to_excel(writer, sheet_name=sheet_name, index=False)


def validate_plate_number(plate_number: str, 
                         pattern: Optional[str] = None) -> bool:
    """
    验证车牌号码格式
    
    参数:
        plate_number (str): 车牌号码
        pattern (str, optional): 正则表达式模式
        
    返回:
        bool: 是否有效
    """
    import re
    
    if not pattern:
        # 默认中国车牌正则
        pattern = r"^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-Z0-9]{5,6}$"
    
    return bool(re.match(pattern, plate_number))


def calculate_fps(start_time: float, frame_count: int) -> float:
    """
    计算帧率
    
    参数:
        start_time (float): 开始时间
        frame_count (int): 帧数
        
    返回:
        float: 帧率
    """
    import time
    elapsed_time = time.time() - start_time
    return frame_count / elapsed_time if elapsed_time > 0 else 0.0


def format_plate_result(plate_number: str,
                       confidence: float,
                       bbox: List[int],
                       timestamp: Optional[str] = None) -> Dict[str, Any]:
    """
    格式化车牌识别结果
    
    参数:
        plate_number (str): 车牌号码
        confidence (float): 置信度
        bbox (List[int]): 边界框坐标
        timestamp (str, optional): 时间戳
        
    返回:
        Dict[str, Any]: 格式化的结果
    """
    return {
        "plate_number": plate_number,
        "confidence": round(confidence, 4),
        "bbox": bbox,
        "timestamp": timestamp or get_timestamp(),
        "is_valid": validate_plate_number(plate_number)
    } 